{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"https://certificate.tpq.io/taim_logo.png\" width=\"350px\" align=\"right\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Artificial Intelligence in Finance"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Execution & Deployment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dr Yves J Hilpisch | The AI Machine\n",
    "\n",
    "http://aimachine.io | http://twitter.com/dyjh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import time\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from pprint import pprint\n",
    "from pylab import plt, mpl\n",
    "plt.style.use('seaborn')\n",
    "mpl.rcParams['savefig.dpi'] = 300\n",
    "mpl.rcParams['font.family'] = 'serif'\n",
    "pd.set_option('mode.chained_assignment', None)\n",
    "pd.set_option('display.float_format', '{:.5f}'.format)\n",
    "np.set_printoptions(suppress=True, precision=4)\n",
    "os.environ['PYTHONHASHSEED'] = '0'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Oanda Account"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "``pip install --upgrade git+https://github.com/yhilpisch/tpqoa.git``"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Configuration file ``aiif.cfg``:\n",
    "\n",
    "    [oanda]\n",
    "    account_id = XYZ-ABC-...\n",
    "    access_token = ZYXCAB...\n",
    "    account_type = practice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tpqoa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "api = tpqoa.tpqoa('../aiif.cfg')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ins = api.get_instruments()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ins[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data Retrieval "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw = api.get_history(instrument='EUR_USD',\n",
    "                      start='2018-01-01',\n",
    "                      end='2020-07-31',\n",
    "                      granularity='D',\n",
    "                      price='A')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw['c'].plot(figsize=(10, 6));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "raw = api.get_history(instrument='EUR_USD',\n",
    "                      start='2020-07-01',\n",
    "                      end='2020-07-31',\n",
    "                      granularity='M1',\n",
    "                      price='M') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw.tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw['c'].plot(figsize=(10, 6));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "api.stream_data('EUR_USD', stop=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Order Execution "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "order = api.create_order('EUR_USD', units=25000,\n",
    "                         suppress=True, ret=True)\n",
    "pprint(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def print_details(order):\n",
    "    details = (order['time'][:-7], order['instrument'], order['units'],\n",
    "               order['price'], order['pl'])\n",
    "    return details"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print_details(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "time.sleep(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "order = api.create_order('EUR_USD', units=-25000,\n",
    "                         suppress=True, ret=True)\n",
    "pprint(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print_details(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "time.sleep(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "order = api.create_order('EUR_USD', units=25000,\n",
    "                         sl_distance=0.005,\n",
    "                         suppress=True, ret=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print_details(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sl_order = api.get_transaction(tid=int(order['id']) + 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sl_order"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(sl_order['time'], sl_order['type'], order['price'],\n",
    " sl_order['price'], sl_order['distance'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "time.sleep(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "order = api.create_order('EUR_USD', units=-25000, suppress=True, ret=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print_details(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "order = api.create_order('EUR_USD', units=25000,\n",
    "                         tsl_distance=0.005,\n",
    "                         suppress=True, ret=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print_details(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tsl_order = api.get_transaction(tid=int(order['id']) + 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tsl_order"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(tsl_order['time'][:-7], tsl_order['type'],\n",
    " order['price'], tsl_order['distance'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "time.sleep(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "order = api.create_order('EUR_USD', units=-25000,\n",
    "                         suppress=True, ret=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print_details(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "time.sleep(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tp_price = round(order['price'] + 0.005, 4)\n",
    "tp_price"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "order = api.create_order('EUR_USD', units=25000,\n",
    "                         tp_price=tp_price,\n",
    "                         suppress=True, ret=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print_details(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tp_order = api.get_transaction(tid=int(order['id']) + 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tp_order"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(tp_order['time'][:-7], tp_order['type'],\n",
    " order['price'], tp_order['price'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "time.sleep(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "order = api.create_order('EUR_USD', units=-25000,\n",
    "                         suppress=True, ret=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print_details(order)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "api.print_transactions(tid=int(order['id']) - 22)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "api.get_account_summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Trading Bot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import oandaenv as oe"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "symbol = 'EUR_USD'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "date = '2020-11-19'  # adjust date to a recent date"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "features = [symbol, 'r', 's', 'm', 'v']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "learn_env = oe.OandaEnv(symbol=symbol,\n",
    "                  start=f'{date} 08:00:00',\n",
    "                  end=f'{date} 13:00:00',\n",
    "                  granularity='S30',\n",
    "                  price='M',\n",
    "                  features=features,\n",
    "                  window=20,\n",
    "                  lags=3,\n",
    "                  leverage=20,\n",
    "                  min_accuracy=0.4,\n",
    "                  min_performance=0.85\n",
    "                 )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.bincount(learn_env.data['d'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learn_env.data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "valid_env = oe.OandaEnv(symbol=learn_env.symbol,\n",
    "                  start=f'{date} 13:00:00',\n",
    "                  end=f'{date} 14:00:00',\n",
    "                  granularity=learn_env.granularity,\n",
    "                  price=learn_env.price,\n",
    "                  features=learn_env.features,\n",
    "                  window=learn_env.window,\n",
    "                  lags=learn_env.lags,\n",
    "                  leverage=learn_env.leverage,\n",
    "                  min_accuracy=0,\n",
    "                  min_performance=0,\n",
    "                  mu=learn_env.mu,\n",
    "                  std=learn_env.std\n",
    "                 )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "valid_env.data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_env = oe.OandaEnv(symbol=learn_env.symbol,\n",
    "                  start=f'{date} 14:00:00',\n",
    "                  end=f'{date} 17:00:00',\n",
    "                  granularity=learn_env.granularity,\n",
    "                  price=learn_env.price,\n",
    "                  features=learn_env.features,\n",
    "                  window=learn_env.window,\n",
    "                  lags=learn_env.lags,\n",
    "                  leverage=learn_env.leverage,\n",
    "                  min_accuracy=0,\n",
    "                  min_performance=0,\n",
    "                  mu=learn_env.mu,\n",
    "                  std=learn_env.std\n",
    "                 )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_env.data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ax = learn_env.data[learn_env.symbol].plot(figsize=(10, 6))\n",
    "plt.axvline(learn_env.data.index[-1], ls='--')\n",
    "valid_env.data[learn_env.symbol].plot(ax=ax, style='-.')\n",
    "plt.axvline(valid_env.data.index[-1], ls='--')\n",
    "test_env.data[learn_env.symbol].plot(ax=ax, style='-.');"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tradingbot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tradingbot.set_seeds(100)\n",
    "agent = tradingbot.TradingBot(24, 0.001, learn_env=learn_env,\n",
    "                              valid_env=valid_env)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "episodes = 31"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%time agent.learn(episodes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tradingbot.plot_performance(agent)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import backtest as bt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "env = test_env"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "bt.backtest(agent, env)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "env.data['p'].iloc[env.lags:].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sum(env.data['p'].iloc[env.lags:].diff() != 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(env.data[['r', 's']].iloc[env.lags:] * env.leverage).sum(\n",
    "        ).apply(np.exp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(env.data[['r', 's']].iloc[env.lags:] * env.leverage).sum(\n",
    "        ).apply(np.exp) - 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(env.data[['r', 's']].iloc[env.lags:] * env.leverage).cumsum(\n",
    "        ).apply(np.exp).plot(figsize=(10, 6));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Deployment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tpqoa"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class OandaTradingBot(tpqoa.tpqoa):\n",
    "    def __init__(self, config_file, agent, granularity, units,\n",
    "                 verbose=True):\n",
    "        super(OandaTradingBot, self).__init__(config_file)\n",
    "        self.agent = agent\n",
    "        self.symbol = self.agent.learn_env.symbol\n",
    "        self.env = agent.learn_env\n",
    "        self.window = self.env.window\n",
    "        if granularity is None:\n",
    "            self.granularity = agent.learn_env.granularity\n",
    "        else:\n",
    "            self.granularity = granularity\n",
    "        self.units = units\n",
    "        self.trades = 0\n",
    "        self.position = 0\n",
    "        self.tick_data = pd.DataFrame()\n",
    "        self.min_length = (self.agent.learn_env.window +\n",
    "                           self.agent.learn_env.lags)\n",
    "        self.pl = list()\n",
    "        self.verbose = verbose\n",
    "    def _prepare_data(self):\n",
    "        self.data['r'] = np.log(self.data / self.data.shift(1))\n",
    "        self.data.dropna(inplace=True)\n",
    "        self.data['s'] = self.data[self.symbol].rolling(\n",
    "                                            self.window).mean()\n",
    "        self.data['m'] = self.data['r'].rolling(self.window).mean()\n",
    "        self.data['v'] = self.data['r'].rolling(self.window).std()\n",
    "        self.data.dropna(inplace=True)\n",
    "        # self.data_ = (self.data - self.env.mu) / self.env.std  # \"correct\" approach\n",
    "        self.data_ = (self.data - self.data.mean()) / self.data.std()  # for demonstration\n",
    "    def _resample_data(self):\n",
    "        self.data = self.tick_data.resample(self.granularity,\n",
    "                        label='right').last().ffill().iloc[:-1]\n",
    "        self.data = pd.DataFrame(self.data['mid'])\n",
    "        self.data.columns = [self.symbol,]\n",
    "        self.data.index = self.data.index.tz_localize(None)\n",
    "    def _get_state(self):\n",
    "        state = self.data_[self.env.features].iloc[-self.env.lags:]\n",
    "        return np.reshape(state.values, [1, self.env.lags,\n",
    "                                         self.env.n_features])\n",
    "    def report_trade(self, time, side, order):\n",
    "        self.trades += 1\n",
    "        pl = float(order['pl'])\n",
    "        self.pl.append(pl)\n",
    "        cpl = sum(self.pl)\n",
    "        print('\\n' + 75 * '=')\n",
    "        print(f'{time} | *** GOING {side} ({self.trades}) ***')\n",
    "        print(f'{time} | PROFIT/LOSS={pl:.2f} | CUMULATIVE={cpl:.2f}')\n",
    "        print(75 * '=')\n",
    "        if self.verbose:\n",
    "            pprint(order)\n",
    "            print(75 * '=')\n",
    "    def on_success(self, time, bid, ask):\n",
    "        df = pd.DataFrame({'ask': ask, 'bid': bid,\n",
    "                           'mid': (bid + ask) / 2},\n",
    "                          index=[pd.Timestamp(time)])\n",
    "        self.tick_data = self.tick_data.append(df)\n",
    "        self._resample_data()\n",
    "        if len(self.data) > self.min_length:\n",
    "            self.min_length += 1\n",
    "            self._prepare_data()\n",
    "            state = self._get_state()\n",
    "            prediction = np.argmax(\n",
    "                self.agent.model.predict(state)[0, 0])\n",
    "            position = 1 if prediction == 1 else -1\n",
    "            if self.position in [0, -1] and position == 1:\n",
    "                order = self.create_order(self.symbol,\n",
    "                        units=(1 - self.position) * self.units,\n",
    "                                suppress=True, ret=True)\n",
    "                self.report_trade(time, 'LONG', order)\n",
    "                self.position = 1\n",
    "            elif self.position in [0, 1] and position == -1:\n",
    "                order = self.create_order(self.symbol,\n",
    "                        units=-(1 + self.position) * self.units,\n",
    "                                suppress=True, ret=True)\n",
    "                self.report_trade(time, 'SHORT', order)\n",
    "                self.position = -1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "otb = OandaTradingBot('../aiif.cfg', agent, '3s',\n",
    "                      25000, verbose=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "otb.tick_data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%time otb.stream_data(agent.learn_env.symbol, stop=1000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('\\n' + 75 * '=')\n",
    "print('*** CLOSING OUT ***')\n",
    "try:\n",
    "    order = otb.create_order(otb.symbol,\n",
    "                    units=-otb.position * otb.units,\n",
    "                    suppress=True, ret=True)\n",
    "    otb.report_trade(otb.time, 'NEUTRAL', order)\n",
    "    if otb.verbose:\n",
    "        pprint(order)\n",
    "    print(75 * '=')\n",
    "except:\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pl = np.array(otb.pl)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pl.cumsum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Saving the Trading Bot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "agent.model.save('tradingbot')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "agent.model = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pickle.dump(agent, open('trading.bot', 'wb'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src='http://hilpisch.com/taim_logo.png' width=\"350px\" align=\"right\">\n",
    "\n",
    "<br><br><br><a href=\"http://tpq.io\" target=\"_blank\">http://tpq.io</a> | <a href=\"http://twitter.com/dyjh\" target=\"_blank\">@dyjh</a> | <a href=\"mailto:ai@tpq.io\">ai@tpq.io</a>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
